package org.pinda.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Logger;

import org.pinda.network.IPacket;
import org.pinda.network.PacketUtils;
import org.pinda.network.auth.IAuthPacket;
import org.pinda.network.auth.PacketHandshake;

public class ClientAccepter extends Thread {
	
	private Logger logger;
	private IServer server;
	private ServerSocket serverSocket;
	
	public ClientAccepter(IServer server, int port) throws IOException {
		super("AuthServer:" + port);
		this.server = server;
		logger = Logger.getLogger(server.getLoggerName());
		serverSocket = new ServerSocket(port);
		logger.info("Hosting on *:" + port);
	}
	
	@Override
	public void run() {
		while(server.keepRunning()) {
			try {
				//Accept Client
				Socket socket = serverSocket.accept();
				ServerClient client = new ServerClient(socket);
				logger.finer("Accepted client from " + client);
				//Wait for auth
				long connectTime = System.currentTimeMillis();
				while(!client.canReadPacket() && (System.currentTimeMillis() - connectTime) < IAuthPacket.AUTH_TIMEOUT) {
					PacketUtils.sleep(10);
				}
				//Check if we timed out
				if((System.currentTimeMillis() - connectTime) >= IAuthPacket.AUTH_TIMEOUT) {
					logger.fine("Authentication time-out from " + client);
					client.close();
					continue;
				}
				//Check Auth
				IPacket packet = PacketUtils.readPacket(server.getServerType(), client.getStream());
				if(packet instanceof IAuthPacket) {
					IAuthPacket authPacket = (IAuthPacket)packet;
					if(authPacket.getId() == PacketHandshake.ID) {
						authPacket.processServer(server.getServerType(), client);
					} else {
						client.close();
						logger.warning("Client auth failed: Protocol Error. Ignoring connection");
					}
				} else {
					client.close();
					logger.warning("Client auth failed: Protocol Error. Ignoring connection");
				}
			} catch (IOException e) {
				logger.warning("Error during auth: " + e.getMessage() + ". Ignoring connection");
			}
		}
	}
	
	public void onShutdown() {
		try {
			serverSocket.close();
		} catch (IOException e) {
			
		}
		logger.info("No longer accepting new clients");
	}

}
